package com.tangyee.home_blood_center.db;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.tangyee.home_blood_center.bean.BSRecord;
import com.tangyee.home_blood_center.utils.DateUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.tangyee.home_blood_center.db.RecordDbSchema.*;

/**
 * 记录的持有者类，封装了一切在界面中需要操作数据库的方法
 */
public class BSRecordHolder {
    private static BSRecordHolder sBSRecordHolder;
    private Context mContext;
    private SQLiteDatabase mDatabase;

    /**
     * 获取本类实例 @param context @return
     */
    public static BSRecordHolder get(Context context) {
        if (sBSRecordHolder == null) sBSRecordHolder = new BSRecordHolder(context);
        return sBSRecordHolder;
    }

    /**
     * 私有化构造方法，借用整个应用的上下文将本类设计成单例 @param context
     */
    private BSRecordHolder(Context context) {
        mContext = context.getApplicationContext();
        mDatabase = new RecordBaseHelper(mContext).getWritableDatabase();
    }

    /**
     * 获得所有的记录，未来数据较大时应去掉，改为 分页查询 @return
     */
    public List<BSRecord> getBSRecords() {
        List<BSRecord> bsRecords = new ArrayList<>();
        RecordCursorWrapper cursor = queryRecords(null, null);
        try {
            cursor.moveToFirst();
            while (!cursor.isAfterLast()) { /* 是否after last (是否在最后一个之后)? 如果否，继续循环*/
                bsRecords.add(cursor.getBsRecord());
                cursor.moveToNext();
            }
        } finally {
            cursor.close();
        }
        return bsRecords;
    }

    /**
     * 获得最新n数量的记录 @param n @return
     */
    public List<BSRecord> getBSRecords(int n) {
        int initNum = n;
        if (initNum < 100) initNum = 100;
        Date date = new Date();
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date = new Date(date.getTime() / 1000 * 1000);
        int count = getRecordsCount();
        if (count == 0) try {
            boolean result = true;
            mDatabase.beginTransaction();
            for (int i = 1; i <= initNum; i++) {
                ContentValues contentValues = getContentValues(new BSRecord(DateUtil.getPreDate(date, initNum - i)));
                if (mDatabase.insert(RecordDbSchema.RecordTable.NAME, null, contentValues) < 0) {
                    result = false;
                    break;
                }
            }
            if (result) mDatabase.setTransactionSuccessful();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != mDatabase) mDatabase.endTransaction();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        Date temp = getLastBSRecord().getDate();
        if (!DateUtil.getDay(date.getTime()).equals(DateUtil.getDay(temp.getTime()))){
            try {
                boolean result = true;
                mDatabase.beginTransaction();
                int dayDiff = (int) DateUtil.getDayDiff(temp, date);
                for (int i = initNum - dayDiff + 1; i <= initNum; i++) {
                    ContentValues contentValues = getContentValues(new BSRecord(DateUtil.getPreDate(date, initNum - i)));
                    if (mDatabase.insert(RecordDbSchema.RecordTable.NAME, null, contentValues) < 0) {
                        result = false;
                        break;
                    }
                }
                if (result) mDatabase.setTransactionSuccessful();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (null != mDatabase) mDatabase.endTransaction();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        int afterCount = getRecordsCount();
        if (afterCount < initNum) try {
            boolean result = true;
            mDatabase.beginTransaction();
            int dayDiff = (int) DateUtil.getDayDiff(temp, date);
            for (int i = afterCount; i <= initNum; i++) {
                ContentValues contentValues = getContentValues(new BSRecord(DateUtil.getPreDate(date, i)));
                if (mDatabase.insert(RecordDbSchema.RecordTable.NAME, null, contentValues) < 0) {
                    result = false;
                    break;
                }
                if (result) mDatabase.setTransactionSuccessful();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (null != mDatabase) mDatabase.endTransaction();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        int s = getRecordsCount();
        return getBSRecords().subList(s - n, s);
    }

    /**
     * 通过time（data）获得记录 @param time @return
     */
    public BSRecord getRSRecordByTime(long time) {/* 有毒有毒有毒！！！*/
        RecordCursorWrapper cursor = queryRecords(RecordDbSchema.RecordTable.Cloumns.DATE + "=" + Long.toString(time), null);
        cursor.moveToFirst();
        if (!cursor.isAfterLast()) return cursor.getBsRecord();
        else return null;
    }

    /**
     * 更新记录到数据库 @param bsRecord
     */
    public void updateDate(BSRecord bsRecord) {
        ContentValues contentValues = getContentValues(bsRecord);
        mDatabase.update(RecordDbSchema.RecordTable.NAME, contentValues, RecordDbSchema.RecordTable.Cloumns.DATE + "=" + Long.toString(bsRecord.getDate().getTime()), null);
    }

    /**
     * 获得最后一条记录 @return
     */
    public BSRecord getLastBSRecord() {
        if (getRecordsCount() == 0) {
            getBSRecords(1);
        }
        BSRecord bsRecord = null;
        RecordCursorWrapper cursor = queryRecords(null, null);
        try {
            cursor.moveToLast();
            bsRecord = cursor.getBsRecord();
        } finally {
            cursor.close();
        }
        return bsRecord;
    }

    /**
     * 获得当前运动记录数 @return
     */
    public int getRecordsCount() {
        int count = 0;
        RecordCursorWrapper cursor = queryRecords(null, null);
        count = cursor.getRecordsCount();
        cursor.close();
        return count;
    }

    /**
     * 将一条记录转换成ContentValues @param bsRecord @return
     */
    private static ContentValues getContentValues(BSRecord bsRecord) {
        ContentValues values = new ContentValues();
        values.put(RecordDbSchema.RecordTable.Cloumns.DATE, bsRecord.getDate().getTime());
        values.put(RecordDbSchema.RecordTable.Cloumns.DAWN, bsRecord.getDawn());
        values.put(RecordDbSchema.RecordTable.Cloumns.BEFORE_BREAKFAST, bsRecord.getBeforeBreakfast());
        values.put(RecordDbSchema.RecordTable.Cloumns.AFTER_BREAKFAST, bsRecord.getAfterBreakfast());
        values.put(RecordDbSchema.RecordTable.Cloumns.BEFORE_LUNCH, bsRecord.getBeforeLunch());
        values.put(RecordDbSchema.RecordTable.Cloumns.AFTER_LUNCH, bsRecord.getAfterLunch());
        values.put(RecordDbSchema.RecordTable.Cloumns.BEFORE_DINNER, bsRecord.getBeforeDinner());
        values.put(RecordDbSchema.RecordTable.Cloumns.AFTER_DINNER, bsRecord.getAfterDinner());
        values.put(RecordDbSchema.RecordTable.Cloumns.BEFORE_SLEEP, bsRecord.getBeforeSleep());
        values.put(RecordDbSchema.RecordTable.Cloumns.SYSTOLIC_BP, bsRecord.getSystolicBP());
        values.put(RecordDbSchema.RecordTable.Cloumns.DIASTOLIC_BP, bsRecord.getDiastolicBP());
        values.put(RecordDbSchema.RecordTable.Cloumns.SACCHARIFICATION_VALUE, bsRecord.getSaccharificationValue());
        return values;
    }

    /**
     * 查询方法 @param whereClause @param whereArgs @return
     */
    private RecordCursorWrapper queryRecords(String whereClause, String[] whereArgs) {
        Cursor cursor = mDatabase.query(RecordDbSchema.RecordTable.NAME, null, whereClause, whereArgs, null, null, RecordDbSchema.RecordTable.Cloumns.DATE);
        return new RecordCursorWrapper(cursor);
    }
}
